package com.tgu.home_action.service.utils;

import com.alibaba.fastjson.JSONObject;
import com.tgu.home_action.pojo.ResponseData;
import com.tgu.home_action.pojo.state.RedisHeader;
import com.tgu.home_action.pojo.state.ResponseState;
import jodd.util.Base64;
import lombok.Setter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Setter
@ConfigurationProperties(prefix = "wx")
public class WXService {
    @Autowired
    private HttpService httpService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${wx.familyAppId}")
    private String familyAppId;
    @Value("${wx.familyAppSecret}")
    private String familyAppSecret;
    @Value("${wx.volunteerAppId}")
    private String volunteerAppId;
    @Value("${wx.volunteerAppSecret}")
    private String volunteerAppSecret;
    @Value("${wx.grantType}")
    private String grantType;
    private String lang;


    /**
     * 微信小程序获取openId,
     *
     * @param code:code
     * @return openid, session_key
     */
    public Map<String, Object> getFamilyOpenId(String code) {
        System.out.println("TestAppid:"+familyAppId);
        System.out.println("TestAppsecret:"+familyAppSecret);

        String url = "https://api.weixin.qq.com/sns/jscode2session";
        Map<String, Object> param = new HashMap<>();
        param.put("appid", familyAppId);
        param.put("secret", familyAppSecret);
        param.put("js_code", code);
        param.put("grant_type", grantType);
        String result = httpService.httpGet(url, param);
        Map<String, Object> res = (Map<String, Object>) JSONObject.parse(result);
        System.out.println(res);
        return res;
    }

    /**
     * 获取志愿者的openid
     */
    public Map<String, Object> getVolunteerOpenId(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        Map<String, Object> param = new HashMap<>();
        param.put("appid", volunteerAppId);
        param.put("secret", volunteerAppSecret);
        param.put("js_code", code);
        param.put("grant_type", grantType);
        String result = httpService.httpGet(url, param);
        Map<String, Object> res = (Map<String, Object>) JSONObject.parse(result);
        System.out.println(res);
        return res;
    }

    /**
     * 获取志愿者的AccessToken
     */
    public Map<String, Object> getVolunteerAccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token";
        Map<String, Object> param = new HashMap<>();
        param.put("grant_type", "client_credential");
        param.put("appid", volunteerAppId);
        param.put("secret", volunteerAppSecret);
        String result = httpService.httpGet(url, param);
        Map<String, Object> res = (Map<String, Object>) JSONObject.parse(result);
        System.out.println(res);
        return res;
    }

    /**
     * 获取志愿者的AccessToken
     */
    public Map<String, Object> getFamilyAccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token";
        Map<String, Object> param = new HashMap<>();
        param.put("grant_type", "client_credential");
        param.put("appid", familyAppId);
        param.put("secret", familyAppSecret);
        String result = httpService.httpGet(url, param);
        Map<String, Object> res = (Map<String, Object>) JSONObject.parse(result);
        System.out.println(res);
        return res;
    }

    /**
     * 小程序获取信息
     */
    public Map<String, Object> getUserInfo(String encryptedData, String sessionkey, String iv) {
        // 被加密的数据
        byte[] dataByte = Base64.decode(encryptedData);
        // 加密秘钥
        byte[] keyByte = Base64.decode(sessionkey);
        // 偏移量
        byte[] ivByte = Base64.decode(iv);
        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                return JSONObject.parseObject(result);
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidParameterSpecException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 发送模板消息
     */
    public Map<String, Object> sendMessage(String accessToken, String openid, String templateId, String page, Map<String, Object> data) {
        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
        Map<String, Object> param = new HashMap<>();
        param.put("touser", openid);
        param.put("template_id", templateId);
        param.put("page", page);
        param.put("data", data);
        String result = httpService.post(url, param);
        Map<String, Object> res = (Map<String, Object>) JSONObject.parse(result);
        System.out.println(res);
        return res;
    }

    /**
     * 获取小程序二维码
     */
    public void getUnlimited(Integer caseId, HttpServletResponse response) {
        String accessToken = stringRedisTemplate.opsForValue().get(RedisHeader.WX_FAMILY_ACCESS_TOKEN.getHeader());
        if (accessToken == null) {
            Map<String, Object> data = getFamilyAccessToken();
            accessToken = (String) data.get("access_token");
            int expiresIn = (int) data.get("expires_in");
            stringRedisTemplate.opsForValue().set(RedisHeader.WX_FAMILY_ACCESS_TOKEN.getHeader(), accessToken, expiresIn, TimeUnit.SECONDS);
        }
        String url = "https://api.weixin.qq.com/wxa/getwxacode?access_token=" + accessToken;
        Map<String, Object> param = new HashMap<>();
//        param.put("access_token",accessToken);
//        param.put("scene",URLEncoder.encode(String.valueOf(caseId), StandardCharsets.UTF_8));
        param.put("path", "pagesA/poster/index?caseId=" + caseId);
        InputStream inputStream = httpService.postGetInputStream(url, param);
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(inputStream);
            OutputStream os = response.getOutputStream();
            int len;
            byte[] arr = new byte[1024];
            while ((len = bis.read(arr)) != -1) {
                os.write(arr, 0, len);
                os.flush();
            }
            os.close();
            bis.close();
            inputStream.close();
//            return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
        } catch (IOException e) {
            e.printStackTrace();
//            return new ResponseData<>(ResponseState.ERROR.getMessage(), ResponseState.ERROR.getValue());
        }
//        Map<String,Object> res = (Map<String, Object>) JSONObject.parse(result);
//        System.out.println(result);
    }
}
